package com.m4f.fse.components.mergers.impl;

import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import com.m4f.fse.components.ifc.SearchEngine;
import com.m4f.fse.model.Metadata;
import com.m4f.fse.model.Query;
import com.m4f.fse.model.Container;
import com.m4f.fse.model.Result;
import java.io.ByteArrayInputStream;

public class GsaMerger extends BaseMerger {
	
	private Query query = new Query();
	
	public GsaMerger() {
		Container<Document> container = new Container<Document>(new Document());
		query.setContainer(container);
	}

	@Override
	public Query merge(final SortedMap<SearchEngine, byte[]> contents) throws Exception {
		SAXBuilder builder = new SAXBuilder();
		builder.setIgnoringElementContentWhitespace(true);
		if(contents.size()>0) {
			Document doc = builder.build(new ByteArrayInputStream(contents.get(contents.firstKey())));
			this.copyMetadata(doc);
		}
		for(byte[] content : contents.values()) {
			Document doc = builder.build(new ByteArrayInputStream(content));
			this.extractResults(doc);
		}
		this.reNumber();
		return this.query;
	}
	
	
	private void reNumber() {
		int count = 1;
		for (Iterator<Result<?>> it = this.query.getResults().iterator(); it.hasNext(); ) {
			Result<Element> result = (Result<Element>) it.next();
			Element resultEl = result.get();
			resultEl.setAttribute("N", "" + count);
			count++;
		}
		
	}
	
	private Document getContent() {
		Container<Document> container = (Container<Document>) this.query.getContainer();
		return container.get();
	}
	
	@SuppressWarnings("unchecked")
	private void copyMetadata(Document doc) {
		Attribute attr = new Attribute("VER", doc.getRootElement().getAttributeValue("VER"));
		Element root = new Element("GSP").setAttribute(attr);
		this.getContent().setRootElement(root);
		List<Element> children = (List<Element>)doc.getRootElement().getChildren();
		for(Element child : children) {
			if(child.getName().equals("RES")) {
				continue;
			}
			this.getContent().getRootElement().addContent((Element)child.clone());
		}
	}
	
	private void extractResults(Document doc) {
		Element root = doc.getRootElement();
		List<Element> children = (List<Element>)root.getChildren();
		for(Element child : children) {
			if(!child.getName().equals("RES")) {
				continue;
			}
			List<Element> resultsList = (List<Element>)child.getChildren("R");
			for(Element resultEl : resultsList) {
				Element relevanceEl = resultEl.getChild("RK");
				Integer relevance = relevanceEl!=null?Integer.parseInt(relevanceEl.getText()):0;
				Result<Element> result = new Result<Element>((Element) resultEl.clone());
				result.setRelevance(relevance);
				this.query.addResult(result);
			}
			this.extractResultsMetaInformation(child);
		}
	}
	
	private void extractResultsMetaInformation(Element resultsEl) {
		List<Element> children = (List<Element>)resultsEl.getChildren();
		for(Element child : children) {
			if(!child.getName().equals("R") && !child.getName().equals("M")) {
				this.query.addResultMetadata(new Metadata<Element>((Element)child.clone()));
			}
		}
	}
	
}